home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / GLUT-3.7 / PROGS / mesademos / REFLECT.C < prev    next >
Encoding:
C/C++ Source or Header  |  1998-08-12  |  8.0 KB  |  380 lines

  1. /* reflect.c */
  2.  
  3. /**
  4.  * Demo of a reflective, texture-mapped surface with OpenGL.
  5.  * Brian Paul  (brianp@ssec.wisc.edu)  August 14, 1995
  6.  *
  7.  * Hardware texture mapping is highly recommended!
  8.  *
  9.  * The basic steps are:
  10.  *    1. Render the reflective object (a polygon) from the normal viewpoint,
  11.  *       setting the stencil planes = 1.
  12.  *    2. Render the scene from a special viewpoint:  the viewpoint which
  13.  *       is on the opposite side of the reflective plane.  Only draw where
  14.  *       stencil = 1.  This draws the objects in the reflective surface.
  15.  *    3. Render the scene from the original viewpoint.  This draws the
  16.  *       objects in the normal fashion.  Use blending when drawing
  17.  *       the reflective, textured surface.
  18.  *
  19.  * This is a very crude demo.  It could be much better.
  20.  */
  21.  
  22. /*
  23.  * Dirk Reiners (reiners@igd.fhg.de) made some modifications to this code.
  24.  *
  25.  * August 1996 - A few optimizations by Brian
  26.  */
  27.  
  28. /* Conversion to GLUT by Mark J. Kilgard */
  29.  
  30. #define USE_ZBUFFER
  31.  
  32. /* OK, without hardware support this is overkill. */
  33. #define USE_TEXTURE
  34.  
  35. #include <math.h>
  36. #include <stdio.h>
  37. #include <stdlib.h>
  38. #include <GL/glut.h>
  39. #include "image.h"
  40.  
  41. #define DEG2RAD (3.14159/180.0)
  42.  
  43. #define TABLE_TEXTURE "brick.rgb"
  44.  
  45. #define MAX_OBJECTS 2
  46.  
  47. static GLint table_list;
  48. static GLint objects_list[MAX_OBJECTS];
  49.  
  50. static GLfloat xrot, yrot;
  51. static GLfloat spin;
  52.  
  53. static void 
  54. make_table(void)
  55. {
  56.   static GLfloat table_mat[] =
  57.   {1.0, 1.0, 1.0, 0.6};
  58.   static GLfloat gray[] =
  59.   {0.4, 0.4, 0.4, 1.0};
  60.  
  61.   table_list = glGenLists(1);
  62.   glNewList(table_list, GL_COMPILE);
  63.  
  64.   /* load table's texture */
  65.   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, table_mat);
  66. /*   glMaterialfv( GL_FRONT, GL_EMISSION, gray ); */
  67.   glMaterialfv(GL_FRONT, GL_DIFFUSE, table_mat);
  68.   glMaterialfv(GL_FRONT, GL_AMBIENT, gray);
  69.  
  70.   /* draw textured square for the table */
  71.   glPushMatrix();
  72.   glScalef(4.0, 4.0, 4.0);
  73.   glBegin(GL_POLYGON);
  74.   glNormal3f(0.0, 1.0, 0.0);
  75.   glTexCoord2f(0.0, 0.0);
  76.   glVertex3f(-1.0, 0.0, 1.0);
  77.   glTexCoord2f(1.0, 0.0);
  78.   glVertex3f(1.0, 0.0, 1.0);
  79.   glTexCoord2f(1.0, 1.0);
  80.   glVertex3f(1.0, 0.0, -1.0);
  81.   glTexCoord2f(0.0, 1.0);
  82.   glVertex3f(-1.0, 0.0, -1.0);
  83.   glEnd();
  84.   glPopMatrix();
  85.  
  86.   glDisable(GL_TEXTURE_2D);
  87.  
  88.   glEndList();
  89. }
  90.  
  91. static void 
  92. make_objects(void)
  93. {
  94.   GLUquadricObj *q;
  95.  
  96.   static GLfloat cyan[] =
  97.   {0.0, 1.0, 1.0, 1.0};
  98.   static GLfloat green[] =
  99.   {0.2, 1.0, 0.2, 1.0};
  100.   static GLfloat black[] =
  101.   {0.0, 0.0, 0.0, 0.0};
  102.  
  103.   q = gluNewQuadric();
  104.   gluQuadricDrawStyle(q, GLU_FILL);
  105.   gluQuadricNormals(q, GLU_SMOOTH);
  106.  
  107.   objects_list[0] = glGenLists(1);
  108.   glNewList(objects_list[0], GL_COMPILE);
  109.   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, cyan);
  110.   glMaterialfv(GL_FRONT, GL_EMISSION, black);
  111.   gluCylinder(q, 0.5, 0.5, 1.0, 15, 10);
  112.   glEndList();
  113.  
  114.   objects_list[1] = glGenLists(1);
  115.   glNewList(objects_list[1], GL_COMPILE);
  116.   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green);
  117.   glMaterialfv(GL_FRONT, GL_EMISSION, black);
  118.   gluCylinder(q, 1.5, 0.0, 2.5, 15, 10);
  119.   glEndList();
  120. }
  121.  
  122. static GLfloat light_pos[] =
  123. {0.0, 20.0, 0.0, 1.0};
  124.  
  125. static void 
  126. init(void)
  127. {
  128.   RGBImageRec *image;
  129.  
  130.   make_table();
  131.   make_objects();
  132.  
  133.   /* Setup texture */
  134. #ifdef USE_TEXTURE
  135.   image = RGBImageLoad(TABLE_TEXTURE);
  136.   gluBuild2DMipmaps(GL_TEXTURE_2D, 3, image->sizeX, image->sizeY,
  137.     GL_RGB, GL_UNSIGNED_BYTE, image->data);
  138.  
  139.   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  140.   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  141.   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  142.   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  143. #endif
  144.  
  145.   xrot = 30.0;
  146.   yrot = 50.0;
  147.   spin = 0.0;
  148.  
  149. #ifndef USE_ZBUFFER
  150.   glEnable(GL_CULL_FACE);
  151. #endif
  152.  
  153.   glShadeModel(GL_FLAT);
  154.  
  155.   glEnable(GL_LIGHT0);
  156.   glEnable(GL_LIGHTING);
  157.  
  158.   glClearColor(0.5, 0.5, 0.5, 1.0);
  159.  
  160.   glEnable(GL_NORMALIZE);
  161. }
  162.  
  163. static void 
  164. reshape(int w, int h)
  165. {
  166.   GLfloat aspect = (float) w / (float) h;
  167.  
  168.   glViewport(0, 0, w, h);
  169.   glMatrixMode(GL_PROJECTION);
  170.   glLoadIdentity();
  171.   glFrustum(-aspect, aspect, -1.0, 1.0, 4.0, 300.0);
  172.   glMatrixMode(GL_MODELVIEW);
  173.   glLoadIdentity();
  174. }
  175.  
  176. /* ARGSUSED */
  177. static void 
  178. draw_objects(GLfloat eyex, GLfloat eyey, GLfloat eyez)
  179. {
  180. #ifndef USE_ZBUFFER
  181.   if (eyex < 0.5) {
  182. #endif
  183.     glPushMatrix();
  184.     glTranslatef(1.0, 1.5, 0.0);
  185.     glRotatef(spin, 1.0, 0.5, 0.0);
  186.     glRotatef(0.5 * spin, 0.0, 0.5, 1.0);
  187.     glCallList(objects_list[0]);
  188.     glPopMatrix();
  189.  
  190.     glPushMatrix();
  191.     glTranslatef(-1.0, 0.85 + 3.0 * fabs(cos(0.01 * spin)), 0.0);
  192.     glRotatef(0.5 * spin, 0.0, 0.5, 1.0);
  193.     glRotatef(spin, 1.0, 0.5, 0.0);
  194.     glScalef(0.5, 0.5, 0.5);
  195.     glCallList(objects_list[1]);
  196.     glPopMatrix();
  197. #ifndef USE_ZBUFFER
  198.   } else {
  199.     glPushMatrix();
  200.     glTranslatef(-1.0, 0.85 + 3.0 * fabs(cos(0.01 * spin)), 0.0);
  201.     glRotatef(0.5 * spin, 0.0, 0.5, 1.0);
  202.     glRotatef(spin, 1.0, 0.5, 0.0);
  203.     glScalef(0.5, 0.5, 0.5);
  204.     glCallList(objects_list[1]);
  205.     glPopMatrix();
  206.  
  207.     glPushMatrix();
  208.     glTranslatef(1.0, 1.5, 0.0);
  209.     glRotatef(spin, 1.0, 0.5, 0.0);
  210.     glRotatef(0.5 * spin, 0.0, 0.5, 1.0);
  211.     glCallList(objects_list[0]);
  212.     glPopMatrix();
  213.   }
  214. #endif
  215. }
  216.  
  217. static void 
  218. draw_table(void)
  219. {
  220.   glCallList(table_list);
  221. }
  222.  
  223. static void 
  224. draw_scene(void)
  225. {
  226.   GLfloat dist = 20.0;
  227.   GLfloat eyex, eyey, eyez;
  228.  
  229.   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
  230.  
  231.   eyex = dist * cos(yrot * DEG2RAD) * cos(xrot * DEG2RAD);
  232.   eyez = dist * sin(yrot * DEG2RAD) * cos(xrot * DEG2RAD);
  233.   eyey = dist * sin(xrot * DEG2RAD);
  234.  
  235.   /* view from top */
  236.   glPushMatrix();
  237.   gluLookAt(eyex, eyey, eyez, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
  238.  
  239.   glLightfv(GL_LIGHT0, GL_POSITION, light_pos);
  240.  
  241.   /* draw table into stencil planes */
  242.   glEnable(GL_STENCIL_TEST);
  243. #ifdef USE_ZBUFFER
  244.   glDisable(GL_DEPTH_TEST);
  245. #endif
  246.   glStencilFunc(GL_ALWAYS, 1, 0xffffffff);
  247.   glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
  248.   glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
  249.   draw_table();
  250.   glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
  251.  
  252. #ifdef USE_ZBUFFER
  253.   glEnable(GL_DEPTH_TEST);
  254. #endif
  255.  
  256.   /* render view from below (reflected viewport) */
  257.   /* only draw where stencil==1 */
  258.   if (eyey > 0.0) {
  259.     glPushMatrix();
  260.  
  261.     glStencilFunc(GL_EQUAL, 1, 0xffffffff);  /* draw if ==1 */
  262.     glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
  263.     glScalef(1.0, -1.0, 1.0);
  264.  
  265.     /* Reposition light in reflected space. */
  266.     glLightfv(GL_LIGHT0, GL_POSITION, light_pos);
  267.  
  268.     draw_objects(eyex, eyey, eyez);
  269.     glPopMatrix();
  270.  
  271.     /* Restore light's original unreflected position. */
  272.     glLightfv(GL_LIGHT0, GL_POSITION, light_pos);
  273.   }
  274.   glDisable(GL_STENCIL_TEST);
  275.  
  276.   glEnable(GL_BLEND);
  277.   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  278.  
  279. #ifdef USE_TEXTURE
  280.   glEnable(GL_TEXTURE_2D);
  281. #endif
  282.   draw_table();
  283.   glDisable(GL_TEXTURE_2D);
  284.   glDisable(GL_BLEND);
  285.  
  286.   /* view from top */
  287.   glPushMatrix();
  288.  
  289.   draw_objects(eyex, eyey, eyez);
  290.  
  291.   glPopMatrix();
  292.  
  293.   glPopMatrix();
  294.  
  295.   glutSwapBuffers();
  296. }
  297.  
  298. /* ARGSUSED1 */
  299. void 
  300. key(unsigned char key, int x, int y)
  301. {
  302.   switch (key) {
  303.   case 27:
  304.     exit(0);
  305.     break;
  306.   }
  307. }
  308.  
  309. /* ARGSUSED1 */
  310. void
  311. special(int key, int x, int y)
  312. {
  313.   switch(key) {
  314.   case GLUT_KEY_UP:
  315.     xrot += 3.0;
  316. #ifndef USE_ZBUFFER
  317.     if (xrot > 180)
  318.       xrot = 180;
  319. #endif
  320.     break;
  321.   case GLUT_KEY_DOWN:
  322.     xrot -= 3.0;
  323. #ifndef USE_ZBUFFER
  324.     if (xrot < 0)
  325.       xrot = 0;
  326. #endif
  327.     break;
  328.   case GLUT_KEY_LEFT:
  329.     yrot += 3.0;
  330.     break;
  331.   case GLUT_KEY_RIGHT:
  332.     yrot -= 3.0;
  333.     break;
  334.   default:
  335.     return;
  336.   }
  337.   glutPostRedisplay();
  338. }
  339.  
  340. static void 
  341. idle(void)
  342. {
  343.   spin += 2.0;
  344.   yrot += 3.0;
  345.   glutPostRedisplay();
  346. }
  347.  
  348. void 
  349. visible(int vis)
  350. {
  351.   if (vis == GLUT_VISIBLE)
  352.     glutIdleFunc(idle);
  353.   else
  354.     glutIdleFunc(NULL);
  355. }
  356.  
  357. int
  358. main(int argc, char *argv[])
  359. {
  360.   glutInitWindowSize(400, 300);
  361.   glutInit(&argc, argv);
  362.   glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB
  363. #ifdef USE_ZBUFFER
  364.     | GLUT_DEPTH
  365. #endif
  366.     | GLUT_STENCIL);
  367.   
  368.   glutCreateWindow("reflect");
  369.   glutReshapeFunc(reshape);
  370.   glutDisplayFunc(draw_scene);
  371.   glutKeyboardFunc(key);
  372.   glutSpecialFunc(special);
  373.   glutVisibilityFunc(visible);
  374.  
  375.   init();
  376.  
  377.   glutMainLoop();
  378.   return 0;             /* ANSI C requires main to return int. */
  379. }
  380.